﻿# -*- coding: utf-8 -*-
from django.template.loader import get_template
from django.template import Template, Context
from django.shortcuts import render
from django.http import HttpResponse
from django.core.mail import send_mail
import django.forms
import django.forms.extras
import pdb
import sys
import datetime
import time

import audi_db.models
from audi_di.path import MSLib

GUARANTEE_ALARM_LIMIT_KM = 3000

MSLib.glogger.at(MSLib.Logs.MSAPI).setlevel(MSLib.SimpleLogger.DEBUG)
MSLib.glogger.at(MSLib.Logs.MSAPI).setident('msapi')

api = MSLib.CarOnlineAPI(daysBack=7)

def normalizeAutoForApi(oid, login, password):
    obj = MSLib.Object()
    obj.isEnabled = True
    obj.targetid = oid
    obj.caronline_login = login
    obj.caronline_password = password
    return obj

class VinSearchForm(django.forms.Form):
    vin = django.forms.CharField()
class GosZnakSearchForm(django.forms.Form):
    gos_znak = django.forms.CharField()
class ClientSearchForm(django.forms.Form):
    surname = django.forms.CharField()
    
class ServiceItemForm(django.forms.Form):
    id = django.forms.IntegerField(initial=0, required=False)
    auto_id = django.forms.IntegerField(initial=0)
    service_in = django.forms.DateTimeField()
    service_out = django.forms.DateTimeField(required=False)
    haul_km = django.forms.IntegerField(required=False)
    is_oil_service = django.forms.BooleanField(initial=False, required=False)
    is_planned_service = django.forms.BooleanField(initial=False, required=False)
    is_finished = django.forms.BooleanField(initial=False, required=False)
    comment_user = django.forms.CharField(widget=django.forms.Textarea, required=False)
    comment_master = django.forms.CharField(widget=django.forms.Textarea, required=False)
    
class ModelForm(django.forms.Form):
    brand = django.forms.CharField()
    model = django.forms.CharField()
    year = django.forms.IntegerField(initial=2015)
    
    guarantee_haul_km = django.forms.IntegerField(initial=100000)
    guarantee_months = django.forms.IntegerField(initial=24)
    
    full_service_schedule_haul_km = django.forms.IntegerField(initial=10000)
    full_service_alarm_haul_km = django.forms.IntegerField(initial=3000)
    
    oil_service_schedule_haul_km = django.forms.IntegerField(initial=3000)
    oil_service_alarm_haul_km = django.forms.IntegerField(initial=1000)

class AutoForm(django.forms.Form):
    id = django.forms.IntegerField(initial=0, required=False)
    model = django.forms.ModelChoiceField(queryset=audi_db.models.AutoModel.objects.all())
    pts_date = django.forms.DateField(initial=datetime.date.today)
    vin = django.forms.CharField()
    guarantee = django.forms.BooleanField(initial=True, required=False)
    registered = django.forms.DateTimeField(initial=datetime.datetime.today)
    #
    gos_znak = django.forms.CharField(required=False)
    colour = django.forms.CharField(required=False)
    #
    seller = django.forms.CharField(required=False)
    sell_date = django.forms.DateField(required=False)
    #service params
    full_service_schedule_haul_km = django.forms.IntegerField(initial=0, required=False)
    full_service_alarm_haul_km = django.forms.IntegerField(initial=0, required=False)
    oil_service_schedule_haul_km = django.forms.IntegerField(initial=0, required=False)
    oil_service_alarm_haul_km = django.forms.IntegerField(initial=0, required=False)
    #owner
    owner_name = django.forms.CharField(required=False)
    owner_surname = django.forms.CharField(required=False)
    owner_paternal = django.forms.CharField(required=False)
    owner_phone = django.forms.CharField(required=False)
    owner_email = django.forms.EmailField(required=False)
    owner_address = django.forms.CharField(required=False)
    #user
    user_name = django.forms.CharField(required=False)
    user_surname = django.forms.CharField(required=False)
    user_paternal = django.forms.CharField(required=False)
    user_phone = django.forms.CharField(required=False)
    user_email = django.forms.EmailField(required=False)
    user_address = django.forms.CharField(required=False)
    #
    comment = django.forms.CharField(widget=django.forms.Textarea, required=False)
    #car-online
    caronline_login = django.forms.CharField(max_length=50)
    caronline_password = django.forms.CharField(max_length=50)

def search(request):
    params = {}
    try:
        vin = VinSearchForm(request.POST)
        params['vin'] = vin       
        client = ClientSearchForm(request.POST)
        params['client'] = client        
        gos_znak = GosZnakSearchForm(request.POST)
        params['gos_znak'] = gos_znak
        
        if vin.is_valid():
            vin = vin.cleaned_data['vin']
            found = audi_db.models.Auto.objects.filter(vin__contains=str(vin))
            if len(found) == 0:
                raise RuntimeError('не найдено ни одной записи vin=%s' % vin)
            if len(found) != 1:
                raise RuntimeError('найдено %d записей vin=%s, уточните поиск' % (len(found), vin))
            params['auto'] = found[0]

        if client.is_valid():
            surname = client.cleaned_data['surname']
            found = audi_db.models.Auto.objects.filter(owner_surname__contains=surname)
            if len(found) == 0:
                raise RuntimeError('не найдено ни одной записи фамилия=%s' % surname)
            if len(found) != 1:
                raise RuntimeError('найдено %d записей фамилия=%s, уточните поиск' % (len(found), surname))
            params['auto'] = found[0]

        if gos_znak.is_valid():
            znak = gos_znak.cleaned_data['gos_znak']
            found = audi_db.models.Auto.objects.filter(gos_znak__contains=znak)
            if len(found) == 0:
                raise RuntimeError('не найдено ни одной записи гос.знак=%s' % znak)
            if len(found) != 1:
                raise RuntimeError('найдено %d записей гос.знак=%s, уточните поиск' % (len(found), znak))
            params['auto'] = found[0]
            
        if 'auto' in params:
            return auto_info(request, auto_id=params['auto'].id)
        else:
            return render(request, 'audi_di/search.html', params)        

    except Exception as err:
        params['error'] = str(err)
        return render(request, 'audi_di/search.html', params)
        
def auto_all(request):
    params = {}
    try:
        params['auto_all'] = audi_db.models.Auto.objects.all()
    except Exception as err:
        params['error'] = str(err)
    return render(request, 'audi_di/allauto.html', params)
    
def forceAutoServiceParams(auto, obj):
    service_items = audi_db.models.ServiceItem.objects.filter(auto=auto).order_by('-service_in')
    obj.service_items = service_items
    for i in service_items:
        if i.is_planned_service and \
                (not hasattr(obj, 'last_planned_service_haul_km') or obj.last_planned_service_haul_km < i.haul_km):
            obj.last_planned_service_haul_km = i.haul_km
            obj.next_planned_service_haul_km = obj.last_planned_service_haul_km + auto.getFullServiceScheduleHaulKm()
            obj.next_planned_service_rest_km = obj.next_planned_service_haul_km - obj.can_milage
            
        if i.is_oil_service and \
                (not hasattr(obj, 'last_oil_service_haul_km') or obj.last_oil_service_haul_km < i.haul_km):
            obj.last_oil_service_haul_km = i.haul_km
            obj.next_oil_service_haul_km = obj.last_oil_service_haul_km + auto.getOilServiceScheduleHaulKm()
            obj.next_oil_service_rest_km = obj.next_oil_service_haul_km - obj.can_milage
            
    if not hasattr(obj, 'last_planned_service_haul_km'):
        obj.last_planned_service_haul_km = 0
        obj.next_planned_service_haul_km = auto.getFullServiceScheduleHaulKm()
        obj.next_planned_service_rest_km = obj.next_planned_service_haul_km - obj.can_milage
        
    if not hasattr(obj, 'last_oil_service_haul_km') or obj.last_oil_service_haul_km < obj.last_planned_service_haul_km:
        obj.last_oil_service_haul_km = obj.last_planned_service_haul_km
        obj.next_oil_service_haul_km = obj.last_oil_service_haul_km + auto.getOilServiceScheduleHaulKm()
        obj.next_oil_service_rest_km = obj.next_oil_service_haul_km - obj.can_milage
        
    obj.next_planned_service_alarm = False
    if obj.next_planned_service_rest_km < auto.getFullServiceAlarmHaulKm():
        obj.next_planned_service_alarm = True            
    obj.next_oil_service_alarm = False
    if obj.next_oil_service_rest_km < auto.getOilServiceAlarmHaulKm():
        obj.next_oil_service_alarm = True

    obj.guarantee_rest_km = auto.model.guarantee_haul_km - obj.can_milage
    obj.guarantee_alarm = False
    if obj.guarantee_rest_km < GUARANTEE_ALARM_LIMIT_KM:
        obj.guarantee_alarm = False
    
def autos_with(request, what=None):
    params = {}
    try:
        if what is None: raise RuntimeError('Системная ошибка - не задан критерий выбора автомобилей')
        
        all = audi_db.models.Auto.objects.all()
        objects = {}
        for auto in all:
            obj = normalizeAutoForApi(auto.id, auto.caronline_login, auto.caronline_password)
            objects[auto.id] = obj
        api.forceInit(objects)
        api.forceCanParams(objects)
        
        autos = []
        for auto in all:
            try:
                obj = objects[auto.id]
                forceAutoServiceParams(auto, obj)
                item = {}
                item['db'] = auto
                item['api'] = obj
                
                if what == 'error':
                    if obj.can_engine_code_error > 0:
                        autos.append(item)
                        
                elif what == 'warning':
                    if obj.can_engine_code_warn1 > 0 or obj.can_engine_code_warn2 > 0:
                        autos.append(item)
                
                elif what == 'planned_service':
                    if obj.next_planned_service_alarm:
                        autos.append(item)
                    
                elif what == 'oil_service':
                    if obj.next_oil_service_alarm:
                        autos.append(item)
                
                elif what == 'guarantee':
                    if obj.guarantee_alarm:
                        autos.append(item)
                        
                else:
                    break
            except Exception as err:
                MSLib.glogger.gdebug('autos_with(%s): auto(%d) force service: %s' % (str(what), auto.id, str(err)))

        params['autos'] = autos
        params['what'] = what
        
    except Exception as err:
        params['error'] = str(err)
    return render(request, 'audi_di/autos_with.html', params)

def auto_info(request, auto_id=0, error=None):
    params = {}
    try:
        auto_id = int(auto_id)
        
        params['header'] = 'Добавление автомобиля'
        if auto_id > 0:
            params['header'] = 'Персональная страница автомобиля'
    
        params['info'] = AutoForm()
        if request.method == 'POST':
            params['info'] = AutoForm(request.POST)
        
        if error: params['error'] = str(error)
        
        if auto_id > 0:
            try:
                auto = audi_db.models.Auto.objects.get(id=auto_id)
            except Exception as err:
                raise RuntimeError('системная ошибка - не найдена запись в базе id=%d, код "%s"' % (auto_id, str(err)))
                
            init = {}
            init['id'] = auto.id
            init['model'] = auto.model
            init['pts_date'] = auto.pts_date
            init['vin'] = auto.vin
            init['guarantee'] = auto.guarantee
            init['registered'] = auto.registered

            fields = \
            [
            'gos_znak', 'colour', 'seller', 'sell_date', 
            'owner_name', 'owner_surname', 'owner_paternal', 'owner_phone', 'owner_email', 'owner_address',
            'user_name', 'user_surname', 'user_paternal', 'user_phone', 'user_email', 'user_address',
            'comment',
            'caronline_login', 'caronline_password'
            ]
            for pname in fields:
                init[pname] = getattr(auto, pname)
                
            init['full_service_schedule_haul_km'] = auto.getFullServiceScheduleHaulKm()
            init['full_service_alarm_haul_km'] = auto.getFullServiceAlarmHaulKm()
            init['oil_service_schedule_haul_km'] = auto.getOilServiceScheduleHaulKm()
            init['oil_service_alarm_haul_km'] = auto.getOilServiceAlarmHaulKm()
            
            params['info'] = AutoForm(initial=init)
                    
            try:
                obj = normalizeAutoForApi(auto.id, auto.caronline_login, auto.caronline_password)
                objects = { auto.id: obj }
                api.forceInit(objects)
                api.forceCanParams(objects)
                api.forceGPSParams(objects)
                forceAutoServiceParams(auto, obj)
            except Exception as err:
                params['caronline_error'] = str(err)
            
            obj = objects[auto.id]
            params['caronline_auto'] = obj
            params['auto'] = auto
            params['auto_id'] = auto.id

    except Exception as err:
        params['error'] = str(err)
    return render(request, 'audi_di/auto.html', params)   
    
def auto_update(request, auto_id=0):
    params = {}
    error = None
    try:
        auto_id = int(auto_id)
        if request.method == 'GET':
            raise RuntimeError('Системная ощибка при обновлении данных автомобиля')
        info = AutoForm(request.POST)
        if not info.is_valid():
            raise RuntimeError('Введены некорректные данные. Исправьте, пожалуйста.')
            
        data = info.cleaned_data
        if auto_id > 0:
            auto = audi_db.models.Auto.objects.get(id=auto_id)
        else:
            auto = audi_db.models.Auto()

        auto.model = data['model']
        auto.pts_date = data['pts_date']
        auto.vin = data['vin']
        auto.guarantee = data['guarantee']
        auto.registered = data['registered']
        
        fields = \
        [
        'gos_znak', 'colour', 'seller', 'sell_date', 
        'full_service_schedule_haul_km',
        'full_service_alarm_haul_km',
        'oil_service_schedule_haul_km',
        'oil_service_alarm_haul_km',
        'owner_name', 'owner_surname', 'owner_paternal', 'owner_phone', 'owner_email', 'owner_address',
        'user_name', 'user_surname', 'user_paternal', 'user_phone', 'user_email', 'user_address',
        'comment',
        'caronline_login', 'caronline_password'
        ]
        for pname in fields:
            if pname in data:
                setattr(auto, pname, data[pname])
        auto.save()
        auto_id = auto.id
        
    except Exception as err:
        error = str(err)
    return auto_info(request, auto_id=auto_id, error=error)
    
def model(request, model_id=0):
    params = {}
    try:
        model_id = int(model_id)
        params['allmodels'] = audi_db.models.AutoModel.objects.all()
        params['model'] = ModelForm()
        if request.method == 'POST':
            params['model'] = ModelForm(request.POST)
        
        if request.method == 'POST' and not params['model'].is_valid():
            raise RuntimeError('Введены некорректные данные. Исправьте, пожалуйста.')
            
        elif request.method == 'POST' and params['model'].is_valid():
            data = params['model'].cleaned_data
            found = audi_db.models.AutoModel.objects.filter(brand=data['brand']).filter(model=data['model']).filter(year=data['year'])
            if len(found) == 0: 
                model = audi_db.models.AutoModel()
            else:
                model = found[0]

            model.brand = data['brand']
            model.model = data['model']
            model.year = data['year']
            model.guarantee_haul_km = data['guarantee_haul_km']
            model.guarantee_months = data['guarantee_months']
            model.full_service_schedule_haul_km = data['full_service_schedule_haul_km']
            model.full_service_alarm_haul_km = data['full_service_alarm_haul_km']
            model.oil_service_schedule_haul_km = data['oil_service_schedule_haul_km']
            model.oil_service_alarm_haul_km = data['oil_service_alarm_haul_km']
            model.save()
            
            params['msg'] = 'Модель %s/%s\'%d успешно зарегистрирована' % (data['brand'], data['model'], data['year'])
            
        if model_id > 0:
            model = audi_db.models.AutoModel.objects.get(id=model_id)
            init = {}
            init['brand'] = model.brand
            init['model'] = model.model
            init['year'] = int(model.year)
            init['guarantee_haul_km'] = int(model.guarantee_haul_km)
            init['guarantee_months'] = int(model.guarantee_months)
            init['full_service_schedule_haul_km'] = int(model.full_service_schedule_haul_km)
            init['full_service_alarm_haul_km'] = int(model.full_service_alarm_haul_km)
            init['oil_service_schedule_haul_km'] = int(model.oil_service_schedule_haul_km)
            init['oil_service_alarm_haul_km'] = int(model.oil_service_alarm_haul_km)

            params['model'] = ModelForm(initial=init)
        
    except Exception as err:
        params['error'] = str(err)
    return render(request, 'audi_di/model.html', params)

def service_item(request, item_id=0):
    params = {}
    try:
        item_id = int(item_id)
        params['service_item'] = ServiceItemForm()
        if request.method == 'POST':
            params['service_item'] = ServiceItemForm(request.POST)

        if request.method == 'POST' and not params['service_item'].is_valid():
            raise RuntimeError('Введены некорректные данные. Исправьте, пожалуйста.')

        elif request.method == 'POST' and params['service_item'].is_valid():
            data = params['service_item'].cleaned_data
            found = audi_db.models.ServiceItem.objects.filter(id=data['id'])
            if len(found) == 0:
                item = audi_db.models.ServiceItem()
            else:
                item = found[0]
                
            item.auto = audi_db.models.Auto.objects.get(id=data['auto_id'])
            item.service_in = data['service_in']
            for p in ['service_out', 'haul_km', 'is_oil_service', 'is_planned_service', 'is_finished', 'comment_user', 'comment_master']:
                if p in data:
                    setattr(item, p, data[p])
            item.save()
            params['msg'] = 'Обращение в сервис успешно зарегистрировано'
            item_id = item.id

        if item_id > 0:
            try:
                item = audi_db.models.ServiceItem.objects.get(id=item_id)
            except Exception as err:
                raise RuntimeError('Отметка об обращении в сервис не найдена')
            init = {}
            init['id'] = item.id
            init['auto_id'] = item.auto.id
            for p in ['service_in', 'service_out', 'haul_km', 'is_oil_service', 'is_planned_service', 'is_finished', 'comment_user', 'comment_master']:
                if getattr(item, p):
                    init[p] = getattr(item, p)
            params['service_item'] = ServiceItemForm(initial=init)

    except Exception as err:
        params['error'] = str(err)
    return render(request, 'audi_di/service_item.html', params)